package cn.itcast.nems.order.dto;

import lombok.Getter;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * 优惠券API请求参数
 * @author ChangLu.Gao
 * @version v1.0
 * @program nems-server
 * @description
 * @date 2023/12/09 17:51
 */
@Getter
public class JournalDiscountApiReqDTO {
    /**
     * 优惠凭单行ID
     * (用于核销时必传)
     */
    private String journalDiscountLineId;
    /**
     * 学员ID,
     * (用于核销时与客户ID二者必传其一)
     */
    private Integer studentId;
    /**
     * 客户ID,
     * (用于核销时与学员ID二者必传其一)
     */
    private String customerId;
    /**
     * 班级ID
     * (用于核销时必传)
     */
    private Integer clazzId;
    /**
     * 业务实际发生时间(为空时默认当前时间)
     */
    private LocalDateTime bizDateTime;
    /**
     * 业务场景
     */
    private Scenario scenario;

    private JournalDiscountApiReqDTO(String journalDiscountLineId
    ) {
        this.journalDiscountLineId = journalDiscountLineId;
    }

    private JournalDiscountApiReqDTO(Integer studentId,
                                     String customerId,
                                     Integer clazzId,
                                     LocalDateTime bizDateTime,
                                     Scenario scenario
    ) {
        this.studentId = studentId;
        this.customerId = customerId;
        this.clazzId = clazzId;
        this.bizDateTime = Objects.requireNonNullElseGet(bizDateTime, LocalDateTime::now);
        this.scenario = scenario;
    }

    private JournalDiscountApiReqDTO(String journalDiscountLineId,
                                     Integer studentId,
                                     String customerId,
                                     Integer clazzId,
                                     LocalDateTime bizDateTime,
                                     Scenario scenario
    ) {
        this.journalDiscountLineId = journalDiscountLineId;
        this.studentId = studentId;
        this.customerId = customerId;
        this.clazzId = clazzId;
        this.bizDateTime = Objects.requireNonNullElseGet(bizDateTime, LocalDateTime::now);
        this.scenario = scenario;
    }

    /**
     * 构建用于根据凭单行ID查询优惠信息的请求体
     *
     * @param journalDiscountLineId 凭单行ID
     * @return 优惠信息
     */
    public static JournalDiscountApiReqDTO buildForQueryByLineId(String journalDiscountLineId
    ) {
        if (null == journalDiscountLineId || journalDiscountLineId.isEmpty()) {
            throw new IllegalArgumentException("journalDiscountLineId is null or empty");
        }
        return new JournalDiscountApiReqDTO(journalDiscountLineId);

    }

    /**
     * 构建用于核销/有效性校验的请求体
     *
     * @param journalDiscountLineId 优惠凭单行ID
     * @param studentId             学员ID
     * @param customerId            客户ID
     * @param clazzId               班级ID
     * @param bizDateTime           业务实际发生时间(为空默认当前时间)
     * @return 用于核销/有效性校验的请求参数
     */
    public static JournalDiscountApiReqDTO buildForWriteOff(String journalDiscountLineId,
                                                            Integer studentId,
                                                            String customerId,
                                                            Integer clazzId,
                                                            LocalDateTime bizDateTime,
                                                            Scenario scenario
    ) {
        if (null == journalDiscountLineId || journalDiscountLineId.isEmpty()) {
            throw new IllegalArgumentException("journalDiscountLineId is null or empty");
        }
        if ((null == studentId || studentId <= 0)
                && (null == customerId || customerId.isEmpty())) {
            throw new IllegalArgumentException("studentId and customerId is null or empty");
        }
        if (null == clazzId || clazzId <= 0) {
            throw new IllegalArgumentException("clazzId is null or empty");
        }
        if (null == scenario) {
            throw new IllegalArgumentException("scenario is null");
        }
        return new JournalDiscountApiReqDTO(journalDiscountLineId, studentId, customerId, clazzId, bizDateTime, scenario);
    }

    /**
     * 构建用于查询可使用优惠单的请求体
     *
     * @param studentId   学员ID
     * @param customerId  客户ID
     * @param clazzId     班级ID
     * @param bizDateTime 业务实际发生时间(为空则默认当前时间)
     * @return 用于查询可使用优惠单的请求参数
     */
    public static JournalDiscountApiReqDTO buildForUsable(Integer studentId,
                                                          String customerId,
                                                          Integer clazzId,
                                                          LocalDateTime bizDateTime,
                                                          Scenario scenario
    ) {
        if ((null == studentId || studentId <= 0)
                && (null == customerId || customerId.isEmpty())) {
            throw new IllegalArgumentException("studentId and customerId is null or empty");
        }
        if (null == clazzId || clazzId <= 0) {
            throw new IllegalArgumentException("clazzId is null or empty");
        }
        if (null == scenario) {
            throw new IllegalArgumentException("scenario is null");
        }
        return new JournalDiscountApiReqDTO(studentId, customerId, clazzId, bizDateTime, scenario);
    }

    /**
     * 获取受影响的对象
     *
     * @return java.lang.String
     * @author 高昌露
     * @since 2023/12/10 11:07
     */
    public String getAffectedCustomerId() {
        if (null != studentId) {
            return studentId.toString();
        }
        return customerId;
    }

    /**
     * 发生场景
     */
    @Getter
    public enum Scenario {
        RENEWAL("升级", List.of(Scenario.CLAZZ_START_DATE, Scenario.FEE_DATE)),
        TRANSFER("转班", List.of(Scenario.CLAZZ_START_DATE, Scenario.FEE_DATE)),
        EMPLOYEE_SIGN_UP("员工替报名", List.of(Scenario.CLAZZ_START_DATE, Scenario.FEE_DATE)),
        SIGN_UP("学员自主报名", List.of(Scenario.CLAZZ_START_DATE, Scenario.FEE_DATE)),
        ;

        Scenario(String desc, List<String> bizDateCheckScope) {
            Desc = desc;
            this.bizDateCheckScope = bizDateCheckScope;
        }

        /**
         * 描述
         */
        private final String Desc;
        /**
         * 业务日期校验范围
         */
        private final List<String> bizDateCheckScope;
        /**
         * 班级开班时间
         */
        public final static String CLAZZ_START_DATE = "CLAZZ_START_DATE";
        /**
         * 缴费时间
         */
        public final static String FEE_DATE = "FEE_DATE";

        /**
         * 根据枚举名称匹配具体枚举
         *
         * @param name 枚举名称
         * @return cn.itcast.nems.order.dto.JournalDiscountApiReqDTO.Scenario 优惠单使用场景枚举
         * @throws IllegalArgumentException 枚举名称不存在时抛出异常
         * @author 高昌露
         * @since 2023/12/20 17:35
         */
        public static Scenario of(String name) throws IllegalArgumentException {
            JournalDiscountApiReqDTO.Scenario scenarioEnum;
            try {
                scenarioEnum = JournalDiscountApiReqDTO.Scenario.valueOf(name);
            } catch (Exception e) {
                throw new IllegalArgumentException(String.format("场景[%s]不存在或错误！", name));
            }
            return scenarioEnum;
        }
    }

    @Override
    public String toString() {
        return "JournalDiscountApiReqDTO{" +
                "journalDiscountLineId='" + journalDiscountLineId + '\'' +
                ", studentId=" + studentId +
                ", customerId='" + customerId + '\'' +
                ", clazzId=" + clazzId +
                ", bizDateTime=" + bizDateTime +
                ", scenario=" + scenario.Desc +
                '}';
    }
}
